home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / Src / Ch7 / Trans.frm (.txt) < prev    next >
Encoding:
Visual Basic Form  |  1999-06-06  |  17.9 KB  |  503 lines

  1. VERSION 5.00
  2. Object = "{F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.2#0"; "COMDLG32.OCX"
  3. Begin VB.Form frmTrans 
  4.    Caption         =   "Trans []"
  5.    ClientHeight    =   2895
  6.    ClientLeft      =   165
  7.    ClientTop       =   735
  8.    ClientWidth     =   3120
  9.    LinkTopic       =   "Form2"
  10.    ScaleHeight     =   2895
  11.    ScaleWidth      =   3120
  12.    StartUpPosition =   3  'Windows Default
  13.    Begin VB.CommandButton cmdTransform 
  14.       Caption         =   "Transform"
  15.       Default         =   -1  'True
  16.       Height          =   375
  17.       Left            =   2160
  18.       TabIndex        =   5
  19.       Top             =   0
  20.       Width           =   855
  21.    End
  22.    Begin VB.PictureBox picResult 
  23.       Height          =   2295
  24.       Left            =   840
  25.       ScaleHeight     =   149
  26.       ScaleMode       =   3  'Pixel
  27.       ScaleWidth      =   157
  28.       TabIndex        =   4
  29.       Top             =   1440
  30.       Visible         =   0   'False
  31.       Width           =   2415
  32.    End
  33.    Begin VB.CommandButton cmdRotate 
  34.       Caption         =   "Rotate"
  35.       Height          =   375
  36.       Left            =   1200
  37.       TabIndex        =   3
  38.       Top             =   0
  39.       Width           =   855
  40.    End
  41.    Begin VB.TextBox txtAngle 
  42.       Height          =   285
  43.       Left            =   600
  44.       TabIndex        =   2
  45.       Text            =   "30"
  46.       Top             =   60
  47.       Width           =   495
  48.    End
  49.    Begin MSComDlg.CommonDialog dlgOpenFile 
  50.       Left            =   0
  51.       Top             =   360
  52.       _ExtentX        =   847
  53.       _ExtentY        =   847
  54.       _Version        =   393216
  55.    End
  56.    Begin VB.PictureBox picOriginal 
  57.       AutoSize        =   -1  'True
  58.       Height          =   2295
  59.       Left            =   120
  60.       ScaleHeight     =   149
  61.       ScaleMode       =   3  'Pixel
  62.       ScaleWidth      =   157
  63.       TabIndex        =   0
  64.       Top             =   480
  65.       Width           =   2415
  66.    End
  67.    Begin VB.Label Label1 
  68.       Caption         =   "Angle"
  69.       Height          =   255
  70.       Left            =   120
  71.       TabIndex        =   1
  72.       Top             =   60
  73.       Width           =   495
  74.    End
  75.    Begin VB.Menu mnuFile 
  76.       Caption         =   "&File"
  77.       Begin VB.Menu mnuFileOpen 
  78.          Caption         =   "&Open..."
  79.          Shortcut        =   ^O
  80.       End
  81.       Begin VB.Menu mnuFileSaveAs 
  82.          Caption         =   "Save &As..."
  83.          Shortcut        =   ^A
  84.       End
  85.    End
  86. Attribute VB_Name = "frmTrans"
  87. Attribute VB_GlobalNameSpace = False
  88. Attribute VB_Creatable = False
  89. Attribute VB_PredeclaredId = True
  90. Attribute VB_Exposed = False
  91. Option Explicit
  92. Private Phi As Single
  93. Private CxIn As Single
  94. Private CyIn As Single
  95. Private CxOut As Single
  96. Private CyOut As Single
  97. ' Map the output pixel (ix_out, iy_out) to the input
  98. ' pixel (x_in, y_in).
  99. Private Sub MapPixel(ByVal ix_out As Single, ByVal iy_out As Single, ByRef x_in As Single, ByRef y_in As Single)
  100. Dim dx As Single
  101. Dim dy As Single
  102. Dim R As Single
  103. Dim theta As Single
  104.     dx = ix_out - CxOut
  105.     dy = iy_out - CyOut
  106.     R = Sqr(dx * dx + dy * dy)
  107.     theta = ATan2(dy, dx)
  108.     x_in = CxIn + R * Cos(theta + Phi)
  109.     y_in = CyIn + R * Sin(theta + Phi)
  110. End Sub
  111. ' Rotate the image.
  112. Private Sub RotateImage(ByVal pic_from As PictureBox, ByVal pic_to As PictureBox, ByVal angle As Single)
  113. Dim white_pixel As RGBTriplet
  114. Dim input_pixels() As RGBTriplet
  115. Dim result_pixels() As RGBTriplet
  116. Dim bits_per_pixel As Integer
  117. Dim xmax_in As Integer
  118. Dim ymax_in As Integer
  119. Dim CxIn As Single
  120. Dim CyIn As Single
  121. Dim CxOut As Single
  122. Dim CyOut As Single
  123. Dim x_in As Single
  124. Dim y_in As Single
  125. Dim ix_in As Integer
  126. Dim iy_in As Integer
  127. Dim ix_out As Integer
  128. Dim iy_out As Integer
  129. Dim dx As Single
  130. Dim dy As Single
  131. Dim radius As Single
  132. Dim theta As Single
  133. Dim dx1 As Single
  134. Dim dx2 As Single
  135. Dim dy1 As Single
  136. Dim dy2 As Single
  137. Dim v11 As Integer
  138. Dim v12 As Integer
  139. Dim v21 As Integer
  140. Dim v22 As Integer
  141.     ' Set the white pixel's value.
  142.     With white_pixel
  143.         .rgbRed = 255
  144.         .rgbGreen = 255
  145.         .rgbBlue = 255
  146.     End With
  147.     ' Get the pixels from pic_from.
  148.     GetBitmapPixels pic_from, input_pixels, bits_per_pixel
  149.     ' Get the pixels from pic_to.
  150.     GetBitmapPixels pic_to, result_pixels, bits_per_pixel
  151.     ' Get the centers of both images.
  152.     CxIn = pic_from.ScaleWidth / 2
  153.     CyIn = pic_from.ScaleHeight / 2
  154.     CxOut = pic_to.ScaleWidth / 2
  155.     CyOut = pic_to.ScaleHeight / 2
  156.     ' Get the size of the original image.
  157.     xmax_in = pic_from.ScaleWidth - 1
  158.     ymax_in = pic_from.ScaleHeight - 1
  159.     ' Calculate the output pixel values.
  160.     For iy_out = 0 To pic_to.ScaleHeight - 1
  161.         For ix_out = 0 To pic_to.ScaleWidth - 1
  162.             ' Map the pixel value from
  163.             ' (ix_out, iy_out) to (x_in, y_in).
  164.             dx = ix_out - CxOut
  165.             dy = iy_out - CyOut
  166.             radius = Sqr(dx * dx + dy * dy)
  167.             theta = ATan2(dy, dx)
  168.             x_in = CxIn + radius * Cos(theta + angle)
  169.             y_in = CyIn + radius * Sin(theta + angle)
  170.             ' Find the nearest integral position.
  171.             ix_in = Int(x_in)
  172.             iy_in = Int(y_in)
  173.             ' See if this is in bounds.
  174.             If (ix_in >= 0) And (ix_in < xmax_in) And _
  175.                (iy_in >= 0) And (iy_in < ymax_in) _
  176.             Then
  177.                 ' The point lies within the image.
  178.                 ' Calculate its value.
  179.                 dx1 = x_in - ix_in
  180.                 dy1 = y_in - iy_in
  181.                 dx2 = 1# - dx1
  182.                 dy2 = 1# - dy1
  183.                 With result_pixels(ix_out, iy_out)
  184.                     ' Calculate the red value.
  185.                     v11 = input_pixels(ix_in, iy_in).rgbRed
  186.                     v12 = input_pixels(ix_in, iy_in + 1).rgbRed
  187.                     v21 = input_pixels(ix_in + 1, iy_in).rgbRed
  188.                     v22 = input_pixels(ix_in + 1, iy_in + 1).rgbRed
  189.                     .rgbRed = _
  190.                         v11 * dx2 * dy2 + v12 * dx2 * dy1 + _
  191.                         v21 * dx1 * dy2 + v22 * dx1 * dy1
  192.                     ' Calculate the green value.
  193.                     v11 = input_pixels(ix_in, iy_in).rgbGreen
  194.                     v12 = input_pixels(ix_in, iy_in + 1).rgbGreen
  195.                     v21 = input_pixels(ix_in + 1, iy_in).rgbGreen
  196.                     v22 = input_pixels(ix_in + 1, iy_in + 1).rgbGreen
  197.                     .rgbGreen = _
  198.                         v11 * dx2 * dy2 + v12 * dx2 * dy1 + _
  199.                         v21 * dx1 * dy2 + v22 * dx1 * dy1
  200.                     ' Calculate the blue value.
  201.                     v11 = input_pixels(ix_in, iy_in).rgbBlue
  202.                     v12 = input_pixels(ix_in, iy_in + 1).rgbBlue
  203.                     v21 = input_pixels(ix_in + 1, iy_in).rgbBlue
  204.                     v22 = input_pixels(ix_in + 1, iy_in + 1).rgbBlue
  205.                     .rgbBlue = _
  206.                         v11 * dx2 * dy2 + v12 * dx2 * dy1 + _
  207.                         v21 * dx1 * dy2 + v22 * dx1 * dy1
  208.                 End With
  209.             Else
  210.                 ' The point is outside the image.
  211.                 ' Use white.
  212.                 result_pixels(ix_out, iy_out) = white_pixel
  213.             End If
  214.         Next ix_out
  215.     Next iy_out
  216.     ' Set pic_to's pixels.
  217.     SetBitmapPixels pic_to, bits_per_pixel, result_pixels
  218.     pic_to.Picture = pic_to.Image
  219. End Sub
  220. ' Transform the image.
  221. Private Sub TransformImage(ByVal pic_from As PictureBox, ByVal pic_to As PictureBox)
  222. Dim white_pixel As RGBTriplet
  223. Dim input_pixels() As RGBTriplet
  224. Dim result_pixels() As RGBTriplet
  225. Dim bits_per_pixel As Integer
  226. Dim ix_max As Single
  227. Dim iy_max As Single
  228. Dim x_in As Single
  229. Dim y_in As Single
  230. Dim ix_out As Integer
  231. Dim iy_out As Integer
  232. Dim ix_in As Integer
  233. Dim iy_in As Integer
  234. Dim dx As Single
  235. Dim dy As Single
  236. Dim dx1 As Single
  237. Dim dx2 As Single
  238. Dim dy1 As Single
  239. Dim dy2 As Single
  240. Dim v11 As Integer
  241. Dim v12 As Integer
  242. Dim v21 As Integer
  243. Dim v22 As Integer
  244.     ' Set the white pixel's value.
  245.     With white_pixel
  246.         .rgbRed = 255
  247.         .rgbGreen = 255
  248.         .rgbBlue = 255
  249.     End With
  250.     ' Get the pixels from pic_from.
  251.     GetBitmapPixels pic_from, input_pixels, bits_per_pixel
  252.     ' Get the pixels from pic_to.
  253.     GetBitmapPixels pic_to, result_pixels, bits_per_pixel
  254.     ' Get the original image's bounds.
  255.     ix_max = pic_from.ScaleWidth - 2
  256.     iy_max = pic_from.ScaleHeight - 2
  257.     ' Calculate the output pixel values.
  258.     For iy_out = 0 To pic_to.ScaleHeight - 1
  259.         For ix_out = 0 To pic_to.ScaleWidth - 1
  260.             ' Map the pixel value from
  261.             ' (ix_out, iy_out) to (x_in, y_in).
  262.             MapPixel ix_out, iy_out, x_in, y_in
  263.             ' Interpolate to find the pixel's value.
  264.             ' Find the nearest integral position.
  265.             ix_in = Int(x_in)
  266.             iy_in = Int(y_in)
  267.             ' See if this is out of bounds.
  268.             If (ix_in < 0) Or (ix_in > ix_max) Or _
  269.                (iy_in < 0) Or (iy_in > iy_max) _
  270.             Then
  271.                 ' The point is outside the image.
  272.                 ' Use white.
  273.                 result_pixels(ix_out, iy_out) = white_pixel
  274.             Else
  275.                 ' The point lies within the image.
  276.                 ' Calculate its value.
  277.                 dx1 = x_in - ix_in
  278.                 dy1 = y_in - iy_in
  279.                 dx2 = 1# - dx1
  280.                 dy2 = 1# - dy1
  281.                 With result_pixels(ix_out, iy_out)
  282.                     ' Calculate the red value.
  283.                     v11 = input_pixels(ix_in, iy_in).rgbRed
  284.                     v12 = input_pixels(ix_in, iy_in + 1).rgbRed
  285.                     v21 = input_pixels(ix_in + 1, iy_in).rgbRed
  286.                     v22 = input_pixels(ix_in + 1, iy_in + 1).rgbRed
  287.                     .rgbRed = _
  288.                         v11 * dx2 * dy2 + v12 * dx2 * dy1 + _
  289.                         v21 * dx1 * dy2 + v22 * dx1 * dy1
  290.         
  291.                     ' Calculate the green value.
  292.                     v11 = input_pixels(ix_in, iy_in).rgbGreen
  293.                     v12 = input_pixels(ix_in, iy_in + 1).rgbGreen
  294.                     v21 = input_pixels(ix_in + 1, iy_in).rgbGreen
  295.                     v22 = input_pixels(ix_in + 1, iy_in + 1).rgbGreen
  296.                     .rgbGreen = _
  297.                         v11 * dx2 * dy2 + v12 * dx2 * dy1 + _
  298.                         v21 * dx1 * dy2 + v22 * dx1 * dy1
  299.                     ' Calculate the blue value.
  300.                     v11 = input_pixels(ix_in, iy_in).rgbBlue
  301.                     v12 = input_pixels(ix_in, iy_in + 1).rgbBlue
  302.                     v21 = input_pixels(ix_in + 1, iy_in).rgbBlue
  303.                     v22 = input_pixels(ix_in + 1, iy_in + 1).rgbBlue
  304.                     .rgbBlue = _
  305.                         v11 * dx2 * dy2 + v12 * dx2 * dy1 + _
  306.                         v21 * dx1 * dy2 + v22 * dx1 * dy1
  307.                 End With
  308.             End If
  309.         Next ix_out
  310.     Next iy_out
  311.     ' Set pic_to's pixels.
  312.     SetBitmapPixels pic_to, bits_per_pixel, result_pixels
  313.     pic_to.Picture = pic_to.Image
  314. End Sub
  315. ' Arrange the controls.
  316. Private Sub ArrangeControls(ByVal angle As Single)
  317. Dim new_wid As Single
  318. Dim new_hgt As Single
  319. Dim old_wid As Single
  320. Dim old_hgt As Single
  321.     ' Calculate the result's size.
  322.     old_wid = picOriginal.ScaleWidth
  323.     old_hgt = picOriginal.ScaleHeight
  324.     new_wid = Abs(old_wid * Cos(angle)) + Abs(old_hgt * Sin(angle))
  325.     new_hgt = Abs(old_wid * Sin(angle)) + Abs(old_hgt * Cos(angle))
  326.     new_wid = ScaleX(new_wid, vbPixels, ScaleMode) + picOriginal.Width - ScaleX(picOriginal.ScaleWidth, vbPixels, ScaleMode)
  327.     new_hgt = ScaleY(new_hgt, vbPixels, ScaleMode) + picOriginal.Height - ScaleY(picOriginal.ScaleHeight, vbPixels, ScaleMode)
  328.     ' Position the result PictureBox.
  329.     picResult.Move _
  330.         picOriginal.Left + picOriginal.Width + 120, _
  331.         picOriginal.Top, new_wid, new_hgt
  332.     picResult.Line (0, 0)-(picResult.ScaleWidth, picResult.ScaleHeight), _
  333.         picResult.BackColor, BF
  334.     picResult.Picture = picResult.Image
  335.     picResult.Visible = True
  336.     ' This makes the image resize itself to
  337.     ' fit the picture.
  338.     picResult.Picture = picResult.Image
  339.     ' Make the form big enough.
  340.     new_wid = picResult.Left + picResult.Width
  341.     If new_wid < cmdTransform.Left + cmdTransform.Width _
  342.         Then new_wid = cmdTransform.Left + cmdTransform.Width
  343.     new_hgt = picResult.Top + picResult.Height
  344.     Move Left, Top, new_wid + 237, new_hgt + 816
  345.     DoEvents
  346. End Sub
  347. ' Rotate the picture.
  348. Private Sub cmdRotate_Click()
  349. Const PI = 3.14159265
  350. Dim angle As Single
  351. Dim start_time As Single
  352.     ' Do nothing if no picture is loaded.
  353.     If picOriginal.Picture = 0 Then Exit Sub
  354.     ' Get the angle of rotation in radians.
  355.     On Error GoTo AngleError
  356.     angle = CSng(txtAngle.Text) * PI / 180
  357.     On Error GoTo 0
  358.     Screen.MousePointer = vbHourglass
  359.     picResult.Line (0, 0)-(picResult.ScaleWidth, picResult.ScaleHeight), _
  360.         picResult.BackColor, BF
  361.     DoEvents
  362.     ' Arrange picResult.
  363.     ArrangeControls angle
  364.     ' Rotate the image.
  365.     start_time = Timer
  366.     RotateImage picOriginal, picResult, angle
  367.     MsgBox Format$(Timer - start_time, "0.00") & " seconds"
  368.     Screen.MousePointer = vbDefault
  369.     Exit Sub
  370. AngleError:
  371.     MsgBox "Invalid angle"
  372.     txtAngle.SetFocus
  373. End Sub
  374. ' Transform the picture.
  375. Private Sub cmdTransform_Click()
  376. Const PI = 3.14159265
  377. Dim start_time As Single
  378.     ' Do nothing if no picture is loaded.
  379.     If picOriginal.Picture = 0 Then Exit Sub
  380.     ' Get the angle of rotation in radians.
  381.     On Error GoTo TransformAngleError
  382.     Phi = CSng(txtAngle.Text) * PI / 180
  383.     On Error GoTo 0
  384.     Screen.MousePointer = vbHourglass
  385.     picResult.Line (0, 0)-(picResult.ScaleWidth, picResult.ScaleHeight), _
  386.         picResult.BackColor, BF
  387.     DoEvents
  388.     ' Arrange picResult.
  389.     ArrangeControls Phi
  390.     ' Get the centers of both images. These are needed
  391.     ' by MapPixel.
  392.     CxIn = picOriginal.ScaleWidth / 2
  393.     CyIn = picOriginal.ScaleHeight / 2
  394.     CxOut = picResult.ScaleWidth / 2
  395.     CyOut = picResult.ScaleHeight / 2
  396.     ' Transform the image.
  397.     start_time = Timer
  398.     TransformImage picOriginal, picResult
  399.     MsgBox Format$(Timer - start_time, "0.00") & " seconds"
  400.     Screen.MousePointer = vbDefault
  401.     Exit Sub
  402. TransformAngleError:
  403.     MsgBox "Invalid angle"
  404.     txtAngle.SetFocus
  405. End Sub
  406. ' Start in the current directory.
  407. Private Sub Form_Load()
  408.     picOriginal.AutoSize = True
  409.     picOriginal.ScaleMode = vbPixels
  410.     picOriginal.AutoRedraw = True
  411.     picResult.ScaleMode = vbPixels
  412.     picResult.AutoRedraw = True
  413.     dlgOpenFile.CancelError = True
  414.     dlgOpenFile.InitDir = App.Path
  415.     dlgOpenFile.Filter = _
  416.         "Bitmaps (*.bmp)|*.bmp|" & _
  417.         "GIFs (*.gif)|*.gif|" & _
  418.         "JPEGs (*.jpg)|*.jpg;*.jpeg|" & _
  419.         "Icons (*.ico)|*.ico|" & _
  420.         "Cursors (*.cur)|*.cur|" & _
  421.         "Run-Length Encoded (*.rle)|*.rle|" & _
  422.         "Metafiles (*.wmf)|*.wmf|" & _
  423.         "Enhanced Metafiles (*.emf)|*.emf|" & _
  424.         "Graphic Files|*.bmp;*.gif;*.jpg;*.jpeg;*.ico;*.cur;*.rle;*.wmf;*.emf|" & _
  425.         "All Files (*.*)|*.*"
  426.     Width = cmdTransform.Left + cmdTransform.Width + 120 + Width - ScaleWidth
  427.     Height = picOriginal.Top + picOriginal.Height + 120 + Height - ScaleHeight
  428. End Sub
  429. ' Load the indicated file.
  430. Private Sub mnuFileOpen_Click()
  431. Dim file_name As String
  432.     ' Let the user select a file.
  433.     On Error Resume Next
  434.     dlgOpenFile.Flags = cdlOFNFileMustExist + cdlOFNHideReadOnly
  435.     dlgOpenFile.ShowOpen
  436.     If Err.Number = cdlCancel Then
  437.         Exit Sub
  438.     ElseIf Err.Number <> 0 Then
  439.         Beep
  440.         MsgBox "Error selecting file.", , vbExclamation
  441.         Exit Sub
  442.     End If
  443.     On Error GoTo 0
  444.     Screen.MousePointer = vbHourglass
  445.     DoEvents
  446.     file_name = Trim$(dlgOpenFile.FileName)
  447.     dlgOpenFile.InitDir = Left$(file_name, Len(file_name) _
  448.         - Len(dlgOpenFile.FileTitle) - 1)
  449.     Caption = "Trans [" & dlgOpenFile.FileTitle & "]"
  450.     ' Open the original file.
  451.     On Error GoTo LoadError
  452.     picOriginal.Picture = LoadPicture(file_name)
  453.     On Error GoTo 0
  454.     ' Hide picResult.
  455.     picResult.Visible = False
  456.     If cmdTransform.Left + cmdTransform.Width > picOriginal.Left + picOriginal.Width Then
  457.         Width = cmdTransform.Left + cmdTransform.Width + 120 + Width - ScaleWidth
  458.     Else
  459.         Width = picOriginal.Left + picOriginal.Width + 120 + Width - ScaleWidth
  460.     End If
  461.     Height = picOriginal.Top + picOriginal.Height + 120 + Height - ScaleHeight
  462.     Screen.MousePointer = vbDefault
  463.     Exit Sub
  464. LoadError:
  465.     Screen.MousePointer = vbDefault
  466.     MsgBox "Error " & Format$(Err.Number) & _
  467.         " opening file '" & file_name & "'" & vbCrLf & _
  468.         Err.Description
  469. End Sub
  470. ' Save the transformed image.
  471. Private Sub mnuFileSaveAs_Click()
  472. Dim file_name As String
  473.     ' Let the user select a file.
  474.     On Error Resume Next
  475.     dlgOpenFile.Flags = cdlOFNOverwritePrompt + cdlOFNHideReadOnly
  476.     dlgOpenFile.ShowSave
  477.     If Err.Number = cdlCancel Then
  478.         Exit Sub
  479.     ElseIf Err.Number <> 0 Then
  480.         Beep
  481.         MsgBox "Error selecting file.", , vbExclamation
  482.         Exit Sub
  483.     End If
  484.     On Error GoTo 0
  485.     Screen.MousePointer = vbHourglass
  486.     DoEvents
  487.     file_name = Trim$(dlgOpenFile.FileName)
  488.     dlgOpenFile.InitDir = Left$(file_name, Len(file_name) _
  489.         - Len(dlgOpenFile.FileTitle) - 1)
  490.     Caption = "Trans [" & dlgOpenFile.FileTitle & "]"
  491.     ' Save the transformed image into the file.
  492.     On Error GoTo SaveError
  493.     SavePicture picResult.Picture, file_name
  494.     On Error GoTo 0
  495.     Screen.MousePointer = vbDefault
  496.     Exit Sub
  497. SaveError:
  498.     Screen.MousePointer = vbDefault
  499.     MsgBox "Error " & Format$(Err.Number) & _
  500.         " saving file '" & file_name & "'" & vbCrLf & _
  501.         Err.Description
  502. End Sub
  503.